<template>
  <div class="search">
    <n-space justify="space-between">
      <n-space align="center">
        <n-button type="primary" style="width: 185px" @click="addMedia"> 添加图片</n-button>
        <n-checkbox
            :checked="checkAll"
            :disabled="mediaStore.mediaList.length === 0"
            @click="handleCheckAll"
            style="margin-left: 10px"
        >
          全选当前页
        </n-checkbox>
        <n-button type="primary" :disabled="checkedList.length < 1" @click="batchDeleteMedia">批量删除</n-button>
      </n-space>
      <n-input-group>
        <n-input
            v-model:value="queryParam.mediaName"
            placeholder="输入文件名查询"
            clearable
        />
        <n-button type="primary" ghost @click="queryMediaByPage(1)">搜索</n-button>
      </n-input-group>
    </n-space>
  </div>
  <div class="content">
    <n-space vertical style="width: 185px">
      <div class="group__search">
        <n-input v-model:value="searchGroupValue" clearable type="text" placeholder="请输入分组关键词"></n-input>
      </div>
      <div class="group">
        <div class="group__list">
          <div
              v-for="item in groupList"
              :key="item.id"
              :class="['group__item', { active: queryParam.groupId === item.id }]"
              @click="clickGroup(item.id)"
          >
            {{ item.groupName }}（{{ item.mediaNum }}）
            <div v-if="![1, -1].includes(item.id)" class="btns-box">
              <n-button quaternary circle @click.stop="renameGroup(item)">
                <template #icon>
                  <n-icon>
                    <x-svg-edit/>
                  </n-icon>
                </template>
              </n-button>
              <n-button quaternary circle @click.stop="deleteGroup(item)">
                <template #icon>
                  <n-icon>
                    <x-svg-delete/>
                  </n-icon>
                </template>
              </n-button>
            </div>
          </div>
        </div>
        <div class="group__item add" @click="addGroup"> 添加分组</div>
      </div>
    </n-space>

    <div class="library">
      <n-checkbox-group v-model:value="checkedList">
        <ul v-if="mediaStore.mediaList[0]" class="library-list">
          <li v-for="item in mediaStore.mediaList" :key="item.id" class="library-item">
            <div class="library-item-inner">
              <div class="cover-box">
                <n-checkbox class="checkbox" :value="item.id" style="width: 100%">
                  <div class="cover">
                    <img :src="item.mediaUrl"/>
                  </div>
                </n-checkbox>
                <div class="btns-bar">
                  <n-icon-wrapper :size="20" @click="handlePreview(item.mediaUrl)">
                    <n-icon>
                      <x-svg-preview/>
                    </n-icon>
                  </n-icon-wrapper>
                </div>
              </div>
              <div class="info-box">
                <p class="info-size">
                      <span class="name ellipsis" :title="item.mediaName">
                        {{ item.mediaName }}
                      </span>
                  <span class="ellipsis" title="2021/7/6">{{ item.createdAt }}</span>
                </p>
              </div>

              <div class="btns-box">
                <x-button type="primary" text @click="renameMedia(item)">
                  改名
                </x-button>
                <x-button
                    type="primary"
                    text
                    @click="changeMediaGroup(item)"
                >
                  分组
                </x-button>
                <n-popconfirm @positive-click="deleteMedia(item.id)" negative-text="取消" positive-text="确认">
                  <template #trigger>
                    <x-button type="error" text>删除</x-button>
                  </template>
                  确认删除该素材？
                </n-popconfirm>
              </div>
            </div>
          </li>
        </ul>
        <x-empty v-else class="empty" description="暂无数据"></x-empty>
      </n-checkbox-group>
      <n-pagination v-if="mediaStore.mediaList[0]" v-model:page="pageInfo.pageNum" :page-count="pageInfo.totalPage"
                    :on-update:page="queryMediaByPage"/>
    </div>
  </div>
  <add-group-modal v-if="groupInfo.show" :modal-data="groupInfo" @success="queryGroup"/>
  <add-media-modal v-if="mediaInfo.show" :modal-data="mediaInfo" @success="addMediaSuccess"/>
  <change-group-modal :modal-data="changeGroupInfo" @success="changeGroupSuccess"/>
  <rename-modal :modal-data="renameInfo" @success="queryMedia"/>
  <n-modal v-model:show="showPreviewModal" preset="card" title="预览" :bordered="false" :style="{ width: '520px' }">
    <div class="flex center">
      <n-image class="preview-img" :src="previewUrl"/>
    </div>
  </n-modal>
</template>

<script setup>
import {
  NButton,
  NCheckbox,
  NCheckboxGroup,
  NIcon,
  NIconWrapper,
  NImage,
  NInput,
  NInputGroup,
  NModal,
  NPagination,
  NPopconfirm,
  NSpace,
  useDialog,
} from 'naive-ui'
import {computed, onBeforeMount, reactive, ref} from "vue";
import {useMediaStore} from "@/store/media";
import XButton from '@/components/x-button.vue'
import XEmpty from '@/components/x-empty.vue'
import AddGroupModal from "@/views/store/components/add-group-modal.vue";
import {reqDeleteMedia, reqDeleteMediaGroup} from "@/api";
import AddMediaModal from "@/views/store/components/add-media-modal.vue";
import ChangeGroupModal from "@/views/store/components/change-group-modal.vue";
import RenameModal from "@/views/store/components/rename-modal.vue";
import XSvgEdit from "@/components/svg/x-svg-edit.vue";
import XSvgDelete from "@/components/svg/x-svg-delete.vue";
import XSvgPreview from "@/components/svg/x-svg-preview.vue";

const searchGroupValue = ref('')
const checkedList = ref([])
const queryParam = reactive({
  groupId: -1,
  mediaName: '',
  pageNum: 1,
  pageSize: 20,
})
const groupInfo = ref({show: false})
const mediaInfo = ref({show: false, groupId: queryParam.groupId})
const changeGroupInfo = ref({show: false, groupId: queryParam.groupId, mediaId: 0})
const renameInfo = ref({show: false, mediaId: 0, mediaName: ''})

const dialog = useDialog()
const mediaStore = useMediaStore()
const groupList = computed(() => {
        const query = searchGroupValue.value.trim()
        if (!query) {
          return mediaStore.mediaGroupList
        }
        return mediaStore.mediaGroupList.filter((item) => item.groupName.toLocaleLowerCase().includes(query.toLocaleLowerCase()))
      })
const mediaList = mediaStore.mediaList
const pageInfo = mediaStore.pageInfo
const checkAll = computed(() => mediaList.length > 0 && mediaList.length === checkedList.value.length)

function addGroup() {
  groupInfo.value = {show: true}
}

async function queryGroup() {
  await mediaStore.loadMediaGroupList()
}

async function clickGroup(groupId) {
  queryParam.groupId = groupId
  queryParam.pageNum = 1
  await queryMedia()
}

function renameGroup(row) {
  groupInfo.value = {show: true, groupId: row.id, groupName: row.groupName}
}

function deleteGroup(row) {
  dialog.warning({
    title: '提示',
    content: `删除后组内元素将全部删除，是否删除${row.groupName}`,
    positiveText: '确认',
    negativeText: '取消',
    onPositiveClick: async () => {
      await reqDeleteMediaGroup(row.id)
      if (row.id === queryParam.groupId) {
        await mediaStore.loadMediaGroupList()
        await clickGroup(groupList[0].id)
      } else {
        const index = groupList.findIndex(item => item.id === row.id)
        groupList.splice(index, 1)
      }
    }
  })
}

async function queryMedia() {
  await mediaStore.loadMediaList(queryParam)
}

async function queryMediaByPage(page) {
  queryParam.pageNum = page
  await queryMedia()
}

function addMedia() {
  mediaInfo.value.show = true;
  mediaInfo.value.groupId = queryParam.groupId
}

async function batchDeleteMedia() {
  dialog.warning({
    title: '提示',
    content: `您选择了${checkedList.value.length}个素材，确认删除？`,
    negativeText: '取消', positiveText: '确认',
    onPositiveClick: () => deleteMedia(-1)
  })
}

async function deleteMedia(id) {
  let ids = id !== -1 ? [id] : checkedList.value;
  if (ids.length <= 0) {
    return;
  }
  await reqDeleteMedia(ids)
  if (mediaList.value.length === ids.length) {
    await queryMediaByPage(queryParam.pageNum > 1 ? queryParam.pageNum - 1 : queryParam.pageNum)
  } else {
    await queryMedia()
  }
  checkedList.value = checkedList.value.filter(item => !ids.includes(item))
  await queryGroup()
}

function changeMediaGroup(row) {
  changeGroupInfo.value = {show: true, groupId: row.groupId, mediaId: row.id}
}

async function addMediaSuccess() {
  mediaInfo.value.show = false
  await queryGroup();
  await queryMedia()
}

async function changeGroupSuccess() {
  if (queryParam.groupId === -1 || mediaList.value.length > 1) {
    await queryMedia()
  } else {
    await queryMediaByPage(queryParam.pageNum > 1 ? queryParam.pageNum - 1 : queryParam.pageNum)
  }
  await queryGroup()
}

function renameMedia(row) {
  renameInfo.value = {show: true, mediaId: row.id, mediaName: row.mediaName}
}

const showPreviewModal = ref(false)
const previewUrl = ref('')

function handlePreview(url) {
  showPreviewModal.value = true
  previewUrl.value = url
}

function handleCheckAll() {
  if (checkAll.value) {
    checkedList.value = []
  } else {
    checkedList.value = mediaList.value.map(item => item.id)
  }
}

onBeforeMount(async () => {
  await queryGroup()
  await queryMedia()
})
</script>

<style lang="scss" scoped>
@import "@/assets/styles/var.scss";

* {
  box-sizing: border-box;
}

ol, ul, li {
  list-style: none;
}

.content {
  display: flex;
  margin-top: 20px;
  min-height: calc(100vh - 280px);

  .group {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    width: 100%;
    overflow: hidden;
    border-radius: 4px;
    box-shadow: 0 0 0 1px #dfe3ed, 0 2px 5px 0 rgb(0 26 91 / 10%);
    height: calc(100vh - 280px);

    &__list {
      flex: 1;
      overflow-y: scroll;
    }

    &__item {
      position: relative;
      width: 100%;
      padding: 15px;
      border-bottom: 1px solid rgba(0, 0, 0, 0.08);
      cursor: pointer;

      .btns-box {
        z-index: 1;
        position: absolute;
        right: 5px;
        top: 50%;
        transform: translateY(-50%);
        display: grid;
        grid-gap: 6px;
        grid-template-columns: 1fr 1fr;
        opacity: 0;
        transition: all 0.2s;
      }

      &.add {
        text-align: center;
        box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.3);
        background: #ffffff;
        color: $primaryColor;
      }

      &:hover {
        color: $primaryColor;
        transition: all 0.3s;

        .btns-box {
          opacity: 1;
          transition: all 0.2s;
        }
      }

      &.active {
        background: #efeff4;
        color: $primaryColor;
        font-weight: bold;
      }
    }
  }

  .library {
    flex: 1;
    margin-left: 20px;

    &-list {
      display: grid;
      grid-template-columns: repeat(5, 1fr);
      grid-gap: 10px;
      width: 100%;
      grid-template-rows: repeat(4, 176px);
      padding: 0;
    }

    &-item {
      position: relative;
      min-height: 176px;

      &-inner {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        min-height: 100%;
        box-shadow: 0 0 0 1px #dfe3ed, 0 2px 5px 0 rgb(0 26 91 / 10%);
        border-radius: 6px;

        &:hover {
          box-shadow: 0 0 0 2px $primaryColor, 0 2px 5px 0 rgb(0 26 91 / 10%);

          .checkbox {
            :deep(.n-checkbox-box) {
              opacity: 1;
            }
          }
        }

        .cover-box {
          width: 100%;
          padding-bottom: 120px;
          height: 0;
          position: relative;
          cursor: pointer;

          .cover {
            border-top-left-radius: 6px;
            border-top-right-radius: 6px;
            border-bottom: 1px solid #dfe3ed;
            background-color: #f8f9fa;
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;

            img,
            video {
              width: 100%;
              height: 100%;
              object-fit: contain;
              border-radius: 2px 2px 0 0;
            }
          }

          .btns-bar {
            position: absolute;
            right: 2px;
            bottom: 2px;

            .icon {
              width: 22px;
              height: 22px;
              border-radius: 4px;
              display: grid;
              align-items: center;
              justify-content: center;
              background: rgba(0, 0, 0, 0.4);
            }
          }
        }

        .info-box {
          padding: 0 10px;
          height: 28px;
          display: flex;
          align-items: center;
          border-bottom-left-radius: 6px;
          border-bottom-right-radius: 6px;

          .info-size {
            display: flex;
            width: 100%;
            justify-content: space-between;
            font-size: 12px;
            color: rgba(0, 0, 0, 0.5);

            .name {
              flex: 1;
              margin-right: 30px;
              color: #313233;
            }
          }
        }

        .btns-box {
          padding: 0 0 10px;
          height: 28px;
          display: flex;
          align-items: center;
          justify-content: center;
        }
      }
    }
  }

  .list {
    flex: 1;

    &__content {
      display: flex;
      flex-wrap: wrap;
      padding: 0 10px;

      &__item {
        position: relative;
        margin: 0 15px 5px 0;
        width: 130px;

        .video {
          max-width: 100%;
          height: 130px;
        }

        &:hover {
          .btn-preview {
            opacity: 1;
            visibility: visible;
            transition: opacity 0.4s;
          }
        }
      }
    }
  }
}

.empty {
  margin-top: 200px;
}

.pagination {
  padding: 20px 0 0;
  display: flex;
  justify-content: flex-end;
}

.checkbox {
  :deep(.n-checkbox-box) {
    z-index: 1;
    position: absolute;
    left: 6px;
    top: 10px;
    opacity: 0;
    transition: all 0.2s ease;
  }

  &[aria-checked='true'] {
    :deep(.n-checkbox-box) {
      opacity: 1;
    }
  }
}
</style>